﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using com.lover.astd.common.manager;
using com.lover.astd.common.model;
using com.lover.common;
using com.lover.common.http;

namespace com.lover.astd.common.partner
{
    public abstract class LoginImplBase
    {
        protected string _username;
        protected string _password;
        protected string _md5_password;
        protected string _md5_password_lower;
        protected Random _rand = new Random();
        protected AccountData _acc;
        protected LoginImplBase() { }
        public void setAccount(AccountData dt) 
        {
            _acc = dt;
            _username = Uri.EscapeDataString(_acc.UserName);
            _password = Uri.EscapeDataString(_acc.Password);
            _md5_password = CommonUtils.generateStringMd5(_acc.Password);
            _md5_password_lower = _md5_password.ToLower();
        }
        public abstract LoginResult login(ref List<Cookie> cookies, string verify_code=null, string extra=null);
        public virtual bool alwaysNeedVerifyCode() { return false; }
        public virtual string getAlwaysCaptchaImageUrl() { return ""; }
        protected void buildAlwaysVerifyResult(ref LoginResult result, ref List<Cookie> cookies)
        {
            result.StatusCode = LoginStatusCode.NeedVerifyCode;
            result.ErrMessage = "需要输入验证码";
            result.CaptchaUrl = getAlwaysCaptchaImageUrl();
            result.CaptchaImage = LoginMgr.getInstance().getCaptchaImage(result.CaptchaUrl, ref cookies);
            result.WebCookies = cookies;
        }
        protected string getGBKEscape(string name)
        {
            byte[] gbk = Encoding.GetEncoding("GBK").GetBytes(name);
            string retString = "";
            foreach (byte b in gbk) retString += string.Format("%{0:X2}", b);
            return retString.ToUpper();
        }
        protected void processRedirect(string redirecturl, LoginResult result, ref List<Cookie> cookies)
        {
            goingToGameUrl();
            HttpResult resp = TransferMgr.doGetPure(redirecturl, ref cookies);
            if (resp == null) { result.StatusCode = LoginStatusCode.FailInGotoGameUrl; return; }

            string location = resp.getExtraHeader("Location");
            if (location == null) { result.StatusCode = LoginStatusCode.FailInGetSession; return; }

            makeSureValidUri(redirecturl, ref location);
            if (!location.Contains("start.action")) processRedirect(location, result, ref cookies);
            processStartGame(location, result, ref cookies);
        }
        protected void processStartGame(string starturl, LoginResult result, ref List<Cookie> cookies, string referer="")
        {
            // location=start.action.....
            gettingSession();
            HttpResult resp = TransferMgr.doGetPure(starturl, ref cookies, referer);
            if (resp == null) { result.StatusCode = LoginStatusCode.FailInGetSession; return; }

            // jsessionid
            result.GameUrl = resp.getExtraHeader("Location");
            List<Cookie> subcooks = resp.getCookies();
            foreach (Cookie subcook in subcooks)
            {
                if (subcook.Name == "JSESSIONID")
                {
                    result.JSessionID = subcook.Value;
                    break;
                }
            }
            result.WebCookies = cookies;
            if (result.JSessionID == null || result.JSessionID == "") result.StatusCode = LoginStatusCode.FailInGetSession;
            else result.StatusCode = LoginStatusCode.Success;
            succeed();
        }
        protected void postStartGame(string starturl, string data, LoginResult result, ref List<Cookie> cookies, string referer = "")
        {
            // location=start.action.....
            gettingSession();
            HttpResult resp = TransferMgr.doPostPure(starturl, data, ref cookies, referer);
            if (resp == null) { result.StatusCode = LoginStatusCode.FailInGetSession; return; }

            // jsessionid
            result.GameUrl = resp.getExtraHeader("Location");
            List<Cookie> subcooks = resp.getCookies();
            foreach (Cookie subcook in subcooks)
            {
                if (subcook.Name == "JSESSIONID")
                {
                    result.JSessionID = subcook.Value;
                    break;
                }
            }
            result.WebCookies = cookies;
            if (result.JSessionID == null || result.JSessionID == "") result.StatusCode = LoginStatusCode.FailInGetSession;
            else result.StatusCode = LoginStatusCode.Success;
            succeed();
        }
        protected void makeSureValidUri(string base_url, ref string now_url)
        {
            if (now_url.StartsWith("http://") || now_url.StartsWith("https://")) return;
            Uri base_uri = new Uri(base_url);
            string scheme = base_uri.Scheme, host = base_uri.Host; 
            int port = base_uri.Port; string portstr = "";
            if(port != 0 && port != 80) portstr = ":" + port;
            string path = base_uri.AbsolutePath;
            int lastSlashIndex = path.LastIndexOf('/');
            if (lastSlashIndex >= 0) path = path.Substring(0, lastSlashIndex);
            if (now_url.StartsWith("./")) now_url = now_url.Substring(1);
            else if (now_url.StartsWith("../"))
            {
                now_url = now_url.Substring(2);
                // 上级目录, 需要再去掉一层目录
                lastSlashIndex = path.LastIndexOf('/');
                if (lastSlashIndex > 0) path = path.Substring(0, lastSlashIndex);
            }
            else if (now_url.StartsWith("/")) { path = ""; }
            else { now_url = "/" + now_url; }
            now_url = String.Format("{0}://{1}{2}{3}{4}", scheme, host, portstr, path, now_url);
        }
        protected void logging() { sendStatus("正在登录..."); }
        protected void findingServerUrl() { sendStatus("正在获取所在区的地址..."); }
        protected void goingToGameUrl() { sendStatus("正在跳转到所在区地址..."); }
        protected void gettingSession() { sendStatus("正在获取会话..."); }
        protected void succeed() { sendStatus("登录完成~~"); }
        private void sendStatus(string status) { LoginMgr.getInstance().sendStatus(status); }
    }
}
